﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VNet.VisiSuite.VisiBoard.BusinessLogic
{

    public class VisiBoxEvent
    {

        public const long LOW_OIL_PRESSURE_1 = 1;
        public const long BROKEN_WIRE_1 = 2;
        public const long HOSE_UNDERSIZE_1 = 4;
        public const long HOSE_OVERSIZE_1 = 8;
        public const long LOW_OIL_PRESSURE_2 = 16;
        public const long BROKEN_WIRE_2 = 32;
        public const long HOSE_UNDERSIZE_2 = 64;
        public const long HOSE_OVERSIZE_2 = 128;
        public const long FRICTION_RUN_OUT = 256;
        public const long TUBE_RUN_OUT = 512;
        public const long OIL_TEMPERATURE = 1024;
        public const long E_STOP = 2048;
        public const long NO_POWER = 4096;
        public const long DOOR_OPEN = 8192;
        public const long DIE_METER_HEAD_1 = 16384;
        public const long DIE_METER_HEAD_2 = 32768;
        public const long BOBBIN_RUN_OUT_INNER_1 = 65536;
        public const long BOBBIN_RUN_OUT_OUTER_1 = 131072;
        public const long BOBBIN_RUN_OUT_INNER_2 = 262144;
        public const long BOBBIN_RUN_OUT_OUTER_2 = 524288;

        public const long RUSCO_CYCLE = 1;
        public const long RUSCO_COOLANT = 2;
        public const long RUSCO_ALARM = 4;
        public const long RUSCO_CYCLE_RUNNING = 8;
        public const long RUSCO_CYCLE_PAUSED = 16;
        public const long RUSCO_CYCLE_RESUME = 32;
        public const long RUSCO_CYCLE_END = 64;
        public const long RUSCO_CYCLE_AUTO = 128;
        public const long RUSCO_PART_CATCHER = 256;


        public const string OFFLINE = "OFFLINE";

        private readonly int _key;
        private readonly DateTime _when;
        private readonly bool _offline;
        private long _status;
        readonly List<string> _downtime_reasons;  // if count == 0 then the VisiBox is running and no downtime events are reported.

        public VisiBoxEvent(int key, DateTime when, bool offline, long status = -1)
        {
            _key = key;
            _when = when;
            _offline = offline;
            _downtime_reasons = new List<string>();
            _status = status;  // -1 = UNDEFINED
        }

        public int key()
        {
            return _key;
        }

        public DateTime time()
        {
            return _when;
        }

        public int reasonCount()
        {
            return _downtime_reasons.Count();
        }

        public string reason(int idx)
        {
            try
            {
                return _downtime_reasons[idx];
            }
            catch
            {
                return null;
            }
        }

        public bool offline()
        {
            return _offline;
        }

        public bool isOfflineEvent()
        {
            return _downtime_reasons.Count == 1 && _downtime_reasons[0] == OFFLINE;
        }

        public void appendReason(string reason)
        {
            if (!string.IsNullOrEmpty(reason) && reason != "Not connected")
            {
                _downtime_reasons.Add(reason);   
            }
        }

        public bool isGoodEvent()
        {
            long stat = status();
            return (stat == 0 || stat == LOW_OIL_PRESSURE_1 || stat == LOW_OIL_PRESSURE_2 || stat == (LOW_OIL_PRESSURE_1 + LOW_OIL_PRESSURE_2));
        }

        public bool isEStop()
        {
            long stat = status();
            return ((stat == E_STOP) || (stat == (E_STOP + NO_POWER)));
        }

        public bool isRunning()
        {
            return (status() == (RUSCO_CYCLE + RUSCO_COOLANT));
        }

        public long status()
        {
            if (_status < 0)
            {
                _status = 0;
                foreach (string reason in _downtime_reasons)
                {
                    if (reason == "Low oil pressure 1")
                        _status += LOW_OIL_PRESSURE_1;
                    else if (reason == "Broken wire 1")
                        _status += BROKEN_WIRE_1;
                    else if (reason == "Hose undersize 1")
                        _status += HOSE_UNDERSIZE_1;
                    else if (reason == "Hose oversize 1")
                        _status += HOSE_OVERSIZE_1;
                    else if (reason == "Low oil pressure 2")
                        _status += LOW_OIL_PRESSURE_2;
                    else if (reason == "Broken wire 2")
                        _status += BROKEN_WIRE_2;
                    else if (reason == "Hose undersize 2")
                        _status += HOSE_UNDERSIZE_2;
                    else if (reason == "Hose oversize 2")
                        _status += HOSE_OVERSIZE_2;
                    else if (reason == "Friction run-out")
                        _status += FRICTION_RUN_OUT;
                    else if (reason == "Tube run-out")
                        _status += TUBE_RUN_OUT;
                    else if (reason == "Oil temperature")
                        _status += OIL_TEMPERATURE;
                    else if (reason == "E-stop")
                        _status += E_STOP;
                    else if (reason == "Run" || reason == "No Power")
                        _status += NO_POWER;
                    else if (reason == "Door Open")
                        _status += DOOR_OPEN;
                    else if (reason == "Die Meter Head 1")
                        _status += DIE_METER_HEAD_1;
                    else if (reason == "Die Meter Head 2")
                        _status += DIE_METER_HEAD_2;
                    else if (reason == "Bobbin Run Out 1st Deck Inner")
                        _status += BOBBIN_RUN_OUT_INNER_1;
                    else if (reason == "Bobbin Run Out 1st Deck Outer")
                        _status += BOBBIN_RUN_OUT_OUTER_1;
                    else if (reason == "Bobbin Run Out 2nd Deck Inner")
                        _status += BOBBIN_RUN_OUT_INNER_2;
                    else if (reason == "Bobbin Run Out 2nd Deck Outer")
                        _status += BOBBIN_RUN_OUT_OUTER_2;

                    else if (reason == "Auto" || reason == "Cycle")
                        _status += RUSCO_CYCLE;
                    else if (reason == "Coolant")
                        _status += RUSCO_COOLANT;
                    else if (reason == "Fault" || reason == "Alarm")
                        _status += RUSCO_ALARM;
                    else if (reason == "Auto Cycle")
                        _status += RUSCO_CYCLE_AUTO;
                    else if (reason == "Cycle Complete")
                        _status += RUSCO_CYCLE_END;
                    else if (reason == "Part Catcher")
                        _status += RUSCO_PART_CATCHER;
                }

            }
            return _status;
        }

    }

}
